package com.zhangmeng.online.exam.controller;

import com.zhangmeng.jwt.dto.LoginUser;
import com.zhangmeng.online.exam.dao.PermissionDao;
import com.zhangmeng.online.exam.dao.RoleDao;
import com.zhangmeng.online.exam.dao.UserDao;
import com.zhangmeng.online.exam.dto.Menu;
import com.zhangmeng.online.exam.dto.Result;
import com.zhangmeng.online.exam.entity.*;
import com.zhangmeng.online.exam.entity.User;
import com.zhangmeng.online.exam.utils.PageUtils;
import com.zhangmeng.online.exam.utils.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.*;

/**
 * @author zm
 * @date 2025/3/5 15:45
 * @version: 1.0
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserDao userDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private PermissionDao permissionDao;

    @Autowired
    private EntityManager entityManager;

    @RequestMapping("/save")
    public Result save(@RequestParam @RequestBody Map<String, Object> params) {
        String id = params.get("id").toString();
        String username = params.get("username").toString();
        String password = params.get("password").toString();
        String email = params.get("email").toString();
        String phone = params.get("phone").toString();
        String status = params.get("status").toString();
        String role_ids = params.get("role_ids").toString();
        String[] role_id_arr = role_ids.split(",");
        Set<Role> roles = new HashSet<>();
        for (String role_id : role_id_arr) {
            Role role = roleDao.findById(Long.parseLong(role_id)).get();
            roles.add(role);
        }
        User user = new User();

        if (id!= null && !id.isEmpty()){
            user = userDao.findById(Long.parseLong(id)).get();
        }

        user.setUsername(username);
        user.setPassword(password);
        user.setEmail(email);
        user.setPhone(phone);
        user.setRoles(roles);
        switch (status) {
            case "1" -> user.setStatus(User.Status.VALID);
            case "0" -> user.setStatus(User.Status.DISABLED);
            case "2" -> user.setStatus(User.Status.LOCKED);
        }
        userDao.save(user);
        return Result.success(user.getId());
    }

    @GetMapping("/list")
    public Result userList(Integer pageNum,Integer pageSize) {

        Pageable pageable = PageRequest.of(PageUtils.getPageNum(pageNum), pageSize, Sort.Direction.DESC, "addTime");
        Page<User> all = userDao.findAll(pageable);
        List<User> list = all.getContent();
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (User user : list) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", user.getId());
            map.put("username", user.getUsername());
            map.put("email", user.getEmail());
            map.put("phone", user.getPhone());
            resultList.add(map);
        }
        return Result.success(pageNum, pageSize, all.getTotalElements(), resultList);
    }

    @RequestMapping("/delete")
    public Result delete(@RequestParam Long id) {
        userDao.deleteById(id);
        return Result.success(null);
    }

    @GetMapping("/getUser")
    public Result getUser( Long id) {
        User user = userDao.findById(id).get();

        Map<String, Object> map = new HashMap<>();
        map.put("id", user.getId());
        map.put("username", user.getUsername());
        map.put("email", user.getEmail());
        map.put("phone", user.getPhone());
        map.put("password", user.getPassword());
        map.put("status", user.getStatus());
        Set<Role> roles = user.getRoles();

        StringBuilder roleIds = new StringBuilder();
        for (Role role : roles) {
            roleIds.append(role.getId()).append(",");
        }

        map.put("role_ids", roleIds);
        return Result.success(map);
    }

    @RequestMapping("/edit")
    public Result edit(@RequestParam @RequestBody Map<String, Object> params) {
        Long id = Long.parseLong(params.get("id").toString());
        String username = params.get("username").toString();
        String password = params.get("password").toString();
        String email = params.get("email").toString();
        String phone = params.get("phone").toString();
        User user = new User();
        user.setId(id);
        user.setUsername(username);
        user.setPassword(password);
        user.setEmail(email);
        user.setPhone(phone);
        userDao.save(user);
        return Result.success(null);
    }

    @RequestMapping("/update")
    public Result update(@RequestBody @RequestParam Map<String, Object> params) {

        String id = params.get("id").toString();
        String fieldName = params.get("fieldName").toString();
        String oldValue = params.get("oldValue").toString();
        String newValue = params.get("newValue").toString();

        User user = userDao.findById(Long.parseLong(id)).get();

        switch (fieldName) {
            case "username" -> user.setUsername(newValue);
            case "password" -> user.setPassword(newValue);
            case "email" -> user.setEmail(newValue);
            case "phone" -> user.setPhone(newValue);
        }

        userDao.save(user);
        return Result.success(null);
    }


    //试卷
    @GetMapping("/menu")
    public Result menuList() {
        List<Menu> list = new ArrayList<>();
        Long currentUserId = UserUtils.getCurrentUserId();

        TypedQuery<User> query = entityManager.createQuery("select obj from User obj where obj.id =:id", User.class);
        query.setParameter("id", currentUserId);
        User root = query.getResultList().get(0);
        Set<Role> roles = root.getRoles();
        for (Role role : roles) {
            Set<Permission> permissions = role.getPermissions();
            for (Permission permission : permissions) {
                if (permission.getParent() == null) {//一级菜单
                    Menu menu = getMenu(permission);
                    list.add(menu);
                }
            }
            if (!list.isEmpty()) {
                for (Permission permission : permissions) {
                    for (Menu map : list) {
                        if (permission.getParent() != null && map.getId().equals(permission.getParent().getId())) {
                            List<Menu> children = map.getChildren();
                            Menu childMap = getMenu(permission);
                            children.add(childMap);
                        }

                    }
                }
            }
        }
        return Result.success(list);
    }

    private static Menu getMenu(Permission permission) {
        Menu childMap = new Menu();
        childMap.setId(permission.getId());
        childMap.setName(permission.getName());
        childMap.setIcon(permission.getIcon());
        childMap.setUrl(permission.getUrl());
        childMap.setDescription(permission.getDescription());
        childMap.setSort(permission.getSort());
        childMap.setChildren(new ArrayList<>());
        return childMap;
    }

    @GetMapping("/getUserInfo")
    public Result getUserInfo() {
        LoginUser principal =(LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = userDao.findById(principal.getId()).get();
        Map<String, Object> map = new HashMap<>();

        Set<Role> roles = user.getRoles();

        map.put("id", user.getId());
        map.put("username", user.getUsername());
        map.put("email", user.getEmail());
        map.put("phone", user.getPhone());
        map.put("password", user.getPassword());
        map.put("type",roles.stream().findFirst().get().getType());
        return Result.success(map);

    }
}